{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "7b16246d-36a3-400b-8fb4-36ed9b821549",
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "import matplotlib\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy\n",
    "import torch\n",
    "import pandas\n",
    "import os\n",
    "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "9a325760-0878-4c77-990e-2ff7ac4035c1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "train_data.shape: (1460, 81)\n",
      "test_data.shape: (1459, 80)\n",
      "all_features: (2919, 80)\n",
      "   Id  MSSubClass MSZoning  LotFrontage  LotArea Street Alley LotShape\n",
      "0   1          60       RL         65.0     8450   Pave   NaN      Reg\n",
      "1   2          20       RL         80.0     9600   Pave   NaN      Reg\n",
      "2   3          60       RL         68.0    11250   Pave   NaN      IR1\n",
      "3   4          70       RL         60.0     9550   Pave   NaN      IR1\n",
      "4   5          60       RL         84.0    14260   Pave   NaN      IR1\n"
     ]
    }
   ],
   "source": [
    "#读取csv数据\n",
    "train_data = pandas.read_csv(\"train.csv\")\n",
    "test_data = pandas.read_csv(\"test.csv\")\n",
    "\n",
    "#把去掉id的数据拼在一起，去掉id的目的是为了防止模型通过记住编号得到对应房价。\n",
    "all_features = pandas.concat(( train_data.iloc[:,1:], test_data.iloc[:,1:]))\n",
    "\n",
    "print(\"train_data.shape:\",train_data.shape)\n",
    "print(\"test_data.shape:\",test_data.shape)\n",
    "print(\"all_features:\",all_features.shape)\n",
    "print(train_data.iloc[:5,:8])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "5fe764d4-a952-44ca-b01d-cf7f4d362aa3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "all_features.shape: (2919, 331)\n"
     ]
    }
   ],
   "source": [
    "#提取全是数字的特征名字\n",
    "numeric_features = all_features.dtypes[all_features.dtypes != 'object'].index\n",
    "\n",
    "#对数据做标准化处理,对应位置赋值\n",
    "all_features[numeric_features] = all_features[numeric_features].apply(lambda x: (x - x.mean()) / (x.std()))\n",
    "\n",
    "# 在标准化数据之后，将缺失值设置为0\n",
    "all_features[numeric_features] = all_features[numeric_features].fillna(0)\n",
    "\n",
    "#`Dummy_na=True` 将“na”（缺失值）视为有效的特征值，并为其创建指示符特征。\n",
    "# pandas.get_dummies把特征为类别值或离散值分成每一个特征为一个类别。\n",
    "all_features = pandas.get_dummies(all_features, dummy_na = True)\n",
    "print(\"all_features.shape:\",all_features.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "c3b23e73-bd12-4b4b-97ad-bfe43569c682",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "train_features.shape: torch.Size([1460, 331])\n",
      "train_features.shape: torch.Size([1459, 331])\n",
      "train_labels: torch.Size([1460, 1])\n"
     ]
    }
   ],
   "source": [
    "#把数据分成训练数据和测试数据\n",
    "n_train = train_data.shape[0]\n",
    "train_features = torch.tensor(all_features[:n_train].values, dtype = torch.float32)\n",
    "test_features = torch.tensor(all_features[n_train:].values, dtype = torch.float32)\n",
    "train_labels = torch.tensor(train_data.SalePrice.values.reshape(-1, 1), dtype = torch.float32)\n",
    "print(\"train_features.shape:\", train_features.shape)\n",
    "print(\"train_features.shape:\", test_features.shape)\n",
    "print(\"train_labels:\", train_labels.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "d5622604-41c1-4ea6-b2e0-b9ff50b8c6d5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "每一批32个，一共46批\n"
     ]
    }
   ],
   "source": [
    "#数据分批\n",
    "batch_size = 32\n",
    "dataset = torch.utils.data.TensorDataset(train_features, train_labels)\n",
    "train_loader = torch.utils.data.DataLoader(dataset,                   # 数据\n",
    "                                          batch_size = batch_size,    # 每个batch大小\n",
    "                                          shuffle = True,             # 是否打乱数据\n",
    "                                          num_workers = 0,            # 工作线程\n",
    "                                          pin_memory = True)\n",
    "print(f\"每一批{len(next(iter(train_loader))[0])}个，一共{len(train_loader)}批\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "bc914fe6-0704-4326-a5ad-f452a516f68e",
   "metadata": {},
   "outputs": [],
   "source": [
    "#定义网络模型\n",
    "class MyNet(torch.nn.Module):\n",
    "    def __init__(self, in_put, hidden, hidden1, out_put):\n",
    "        super().__init__()\n",
    "        self.linear1 = torch.nn.Linear(in_put, hidden)\n",
    "        self.linear2 = torch.nn.Linear(hidden, hidden1)\n",
    "        self.linear3 = torch.nn.Linear(hidden1, out_put)\n",
    "    def forward(self, data): \n",
    "        x = self.linear1(data)\n",
    "        x = torch.relu(x)\n",
    "        x = self.linear2(x)\n",
    "        x = torch.relu(x)\n",
    "        x = self.linear3(x)\n",
    "        return x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "1be716ff-7909-4fca-98dc-58fc00d27afc",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "in_features: 331\n",
      "in_features: torch.Size([1460, 331])\n",
      "MyNet(\n",
      "  (linear1): Linear(in_features=331, out_features=200, bias=True)\n",
      "  (linear2): Linear(in_features=200, out_features=100, bias=True)\n",
      "  (linear3): Linear(in_features=100, out_features=1, bias=True)\n",
      ")\n"
     ]
    }
   ],
   "source": [
    "#取出输入特征个数\n",
    "in_features = train_features.shape[1]\n",
    "hidden, hidden1 ,out_put = 200, 100, 1\n",
    "model = MyNet(in_features, hidden, hidden1, out_put).to(device)\n",
    "\n",
    "#损失函数 loss(xi,yi)=(xi−yi)2\n",
    "loss = torch.nn.MSELoss()\n",
    "\n",
    "#梯度优化算法\n",
    "learn_rate = 1e-2\n",
    "optimizer = torch.optim.Adam(model.parameters(), learn_rate)\n",
    "\n",
    "print(\"in_features:\",in_features)\n",
    "print(\"in_features:\",train_features.shape)\n",
    "print(model)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c5f4c53f-8d34-401a-b422-562796c48239",
   "metadata": {},
   "outputs": [],
   "source": [
    "epochs = 200\n",
    "def train(train_loader):\n",
    "    train_ls = []\n",
    "    for epoch in range(epochs):\n",
    "        loss_sum = 0\n",
    "        for train_batch, labels_batch in train_loader:\n",
    "            train_batch, labels_batch = train_batch.to(device), labels_batch.to(device)\n",
    "            #preds = torch.clamp(model(train_batch), 1, float('inf'))\n",
    "            #l = loss(torch.log(preds), torch.log(labels_batch))\n",
    "            l = loss(model(train_batch),labels_batch)\n",
    "            optimizer.zero_grad()\n",
    "            l.backward()\n",
    "            optimizer.step()\n",
    "            loss_sum += l.item()\n",
    "        train_ls.append(loss_sum)\n",
    "    plt.plot(range(epochs), train_ls)\n",
    "    plt.show()\n",
    "train(train_loader)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2b3404ab-dcd7-458f-905f-fe41878b8f2d",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
